package initialize

import (
	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/circuitbreaker"
	"github.com/alibaba/sentinel-golang/core/config"
	"github.com/alibaba/sentinel-golang/core/flow"
	"github.com/alibaba/sentinel-golang/logging"
	"go.uber.org/zap"
	"mxshop-api/user-web/global"
)

type stateChangeTestListener struct {
}

func (s *stateChangeTestListener) OnTransformToClosed(prev circuitbreaker.State, rule circuitbreaker.Rule) {
	//fmt.Printf("rule.steategy: %+v, From %s to Closed, time: %d\n", rule.Strategy, prev.String(), util.CurrentTimeMillis())
}

func (s *stateChangeTestListener) OnTransformToOpen(prev circuitbreaker.State, rule circuitbreaker.Rule, snapshot interface{}) {
	//fmt.Printf("rule.steategy: %+v, From %s to Open, snapshot: %.2f, time: %d\n", rule.Strategy, prev.String(), snapshot, util.CurrentTimeMillis())
}

func (s *stateChangeTestListener) OnTransformToHalfOpen(prev circuitbreaker.State, rule circuitbreaker.Rule) {
	//fmt.Printf("rule.steategy: %+v, From %s to Half-Open, time: %d\n", rule.Strategy, prev.String(), util.CurrentTimeMillis())
}

func InitSentinel() {
	// 限流
	//先初始化sentinel
	err := sentinel.InitDefault()
	if err != nil {
		zap.S().Fatalf("初始化sentinel 异常: %v", err)
	}

	//配置限流规则
	var ruleQpsList []*flow.Rule
	for _, data := range global.ServerConfig.SentinelQpsInfo {
		ruleQpsList = append(ruleQpsList, &flow.Rule{
			Resource:               data.Resource,
			Threshold:              float64(data.Threshold),
			TokenCalculateStrategy: flow.TokenCalculateStrategy(data.TokenCalculateStrategy),
			ControlBehavior:        flow.ControlBehavior(data.ControlBehavior),
			StatIntervalInMs:       uint32(data.StatIntervalInMs),
			WarmUpColdFactor:       uint32(data.WarmUpPeriodSec),
		})
	}

	_, err = flow.LoadRules(ruleQpsList)
	if err != nil {
		zap.S().Fatalf("加载[限流]规则失败: %v", err)
	}

	// 熔断
	conf := config.NewDefaultConfig()
	// for testing, logging output to console
	conf.Sentinel.Log.Logger = logging.NewConsoleLogger()
	err = sentinel.InitWithConfig(conf)
	if err != nil {
		zap.S().Fatal(err)
	}
	// 注册一个状态变化监听器，这样我们就可以观察到内部断路器的状态变化
	circuitbreaker.RegisterStateChangeListeners(&stateChangeTestListener{})

	//配置熔断规则
	var ruleBreakerList []*circuitbreaker.Rule
	for _, data := range global.ServerConfig.SentinelBreakerInfo {
		ruleBreakerList = append(ruleBreakerList, &circuitbreaker.Rule{
			Resource:         data.Resource,
			Strategy:         circuitbreaker.Strategy(data.Strategy),
			RetryTimeoutMs:   uint32(data.RetryTimeoutMs),
			MinRequestAmount: uint64(data.MinRequestAmount),
			StatIntervalMs:   uint32(data.StatIntervalMs),
			Threshold:        data.Threshold,
		})
	}
	_, err = circuitbreaker.LoadRules(ruleBreakerList)
	if err != nil {
		zap.S().Fatalf("加载[熔断]规则失败: %v", err)
	}
	zap.S().Debug("[user-web] 初始化 熔断限流")
}
